import {initStatus} from "./state.js";
import {compilerToFunction} from "./compile/index.js";
import {mountComponent} from "./lifecycle.js";
import {mergeOptions} from "./utils.js";

export function initMixin(Vue){
    // 给Vue原型添加一个初始化方法
    Vue.prototype._init = function (options){
        const vm = this
        // this.constructor就是当前的大Vue，获取的是Vue上的静态属性
        // this.constructor.options 拿到的就是mixin合并后的数据
        // 然后再把用户写的options和mixin中的进行再次合并
        vm.$options = mergeOptions(this.constructor.options,options)
        // 初始化之前调用beforeCreated
        callHook(vm,"beforeCreated")
        // 初始化状态
        initStatus(vm)
        // 初始化之后调用created
        callHook(vm,"created")
        // 解析模板字符串
        if(vm.$options.el){
            vm.$mount(vm.$options.el)
        }
    }

    // 在原型链上添加$mount方法，用户获取页面模板
    Vue.prototype.$mount = function (el){
        let template;
        const vm = this
        el = document.querySelector(el)
        const opts = vm.$options
        // 判断配置中是否已经存在template，如果没有，则根据el获取页面模板
        if(!opts.render){
            if(!opts.template && opts.el){
                // 拿到模板字符串
                template = el.outerHTML
            }
            if(opts.template){
                template = opts.template
            }
            if(template){
                // 这里拿到模板开始进行模板编译
                opts.render = compilerToFunction(template)
            }
        }
        // 有了render函数，开始对组件进行挂载
        mountComponent(vm,el)
    }
}

function callHook(vm,hook){
    // 拿到用户传入的钩子函数
    const handlers = vm.$options[hook]
    if(handlers){
        // 遍历钩子函数，执行钩子函数
        for(let i=0;i<handlers.length;i++){
            handlers[i].call(vm)
        }
    }
}